<?php

class Utility_NumberFunctions {

    static public function toPrecision($num, $int_sigfigs) {
        $dp = floor($int_sigfigs - log10(abs($num)));

        // Round as a regular number.
        $num = round($num, $dp);

        // strange bug?
        // this fix from: http://jetlogs.org/2008/02/05/php-problems-with-big-integers-and-scientific-notation/
        $num = number_format($num, 0, '.', '');

        return $num;
    }

    static public function countDigits($num) {
        $str = (string) $num;

        $int_digits = 0;
        for($i = 0; $i < strlen($str); $i++) {
            if(is_numeric($str[$i])) {
                $int_digits++;
            }
        }

        return $int_digits;
    }

    static public function toRoman($mix_number, $arr_options = array()) {

        // only convert numbers
        if(!is_string($mix_number) && !is_numeric($mix_number)) {
            return null;
        }

        // ensure an integer
        $int_number = intval($mix_number);
        $int_original = $int_number;

        $str_number = '';

        // map of numbers to letters
        $arr_numerals = array(
            1000000     => 'M',
            900000      => 'CM',
            500000      => 'D',
            400000      => 'CD',
            100000      => 'C',
            90000       => 'XC',
            50000       => 'L',
            40000       => 'XL',
            10000       => 'X',
            9000        => 'IX',
            5000        => 'V',
            4000        => 'IV',
            1000        => 'M',
            900         => 'CM',
            500         => 'D',
            400         => 'CD',
            100         => 'C',
            90          => 'XC',
            50          => 'L',
            40          => 'XL',
            10          => 'X',
            9           => 'IX',
            5           => 'V',
            4           => 'IV',
            1           => 'I'
        );

        $bln_brackets = false;
        foreach ($arr_numerals as $int_value => $str_roman) {

            // divide to get matches
            $int_matches = intval($int_number / $int_value);

            // assign roman numeral times the number of matches
            $str_number .= str_repeat($str_roman, $int_matches);

            // modify the original number and repeat
            $int_number = $int_number % $int_value;

            // if this is a high-order number, then encapsulate number in brackets
            if(($int_original > 4000) && ($int_number < 4000) && !$bln_brackets) {
                $str_number = '(' . $str_number . ')';
                $bln_brackets = true;
            }

        }

        if(isset($arr_options['use_css']) && ($arr_options['use_css'])) {
            $str_number = str_replace(array('(',')'), array('<span style="text-decoration: overline;">', '</span>'), $str_number);
        }

        return $str_number;

    }

    static public function calculatePercentageChange($start, $end)
    {
        return ($start != 0) ? (($end - $start) / $start) * 100 : null;
    }

    static public function listNumberRanges(array $data)
    {

        sort($data);
        
        $first = array_shift($data);

        $parts = array(
            $first
        );

        $previous = $first;

        $inSequence = false;
        foreach ($data as $key => $number) {
            if ($number == ($previous+1)) {
                if (!$inSequence) {
                    $parts[] = '-';
                    $inSequence = true;
                }
            } else if ($number != ($previous+1)) {
                if (!$inSequence) {
                    $parts[] = ', ';
                    $parts[] = $number;
                } else {
                    $parts[] = $previous;
                    $parts[] = ', ';
                    $parts[] = $number;
                }
                
                $inSequence = false;
            }

            $previous = $number;
        }

        if ($previous != $first && ($parts[count($parts)-1] != $previous)) {
            $parts[] = $previous;
        }

        return implode('', $parts);

    }

}
